Welcome to EOELAB!

EOELAB 运维手册

EOELAB 运维手册

本文档面向运维人员,说明如何操作本地域、数据设施、网络设施以及加入联邦。

阅读导览

本地域节点初始化

基础配置

  1. 安装 Debian stable + Incus stable(https://github.com/zabbly/incus)
  2. 根文件系统使用 Btrfs,并配置 raid1/10
  3. 主机名使用 DomainPrefix-Number 格式,例如 core0-1
  4. 禁用 swap:
    • 安装系统时不创建 swap 分区,或
    • 执行 swapoff -a 并永久移除 /etc/fstab 中的 swap 条目
  5. 仅使用 SSH 密钥登录,关闭密码验证
  6. 确认时间通过 systemd-timesyncd 同步 UTC,无需额外配置 NTP

大页内存配置

静态大页

  1. 关闭 THP(参考 https://anotherboringtechblog.com/2024/02/disabling-thp-ubuntu-22-04/)
  2. 添加 /etc/sysctl.d/hugepages.conf,内容为:
    vm.nr_hugepages = SIZE
    
    其中 SIZE = HP_Capacity / 2MiB

注意:当前 Incus 的内存占用统计只统计 4k 大小的普通页,因此实例使用大页内存时,要额外关注 hugetlb 余量。

THP

Debian 默认开启 THP。对于 JVM,额外添加 -XX:+UseTransparentHugePages 标志显式激活。

计算设施操作

生成 TLS 客户端证书

openssl req -newkey rsa:2048 -nodes -keyout client.key -x509 -days 3650 -out client.crt -subj "/CN=Common Name"

在本地域节点添加信任证书:

incus config trust add-certificate client.crt

导出 pfx 证书供浏览器使用:

openssl pkcs12 -export -out client.pfx -inkey client.key -in client.crt

CLI 连接:

mv client.key client.crt ~/.config/incus/
incus remote add ALIAS IP/NS --accept-certificate

OIDC 接入

OIDC 鉴权通过添加联邦认证设施(Zitadel)实现。具体配置参考认证设施 endpoint:https://authn.eoelab.org

Incus + OpenFGA 权限模型

Incus 使用 OpenFGA 实现基于关系的访问控制(ReBAC)。它不是传统的“角色对应固定菜单”,而是由 Incus 针对每次 API 请求检查:

用户或组 + entitlement + Incus 对象 = 是否允许

例如,为 user:alice 建立 project:devoperator 关系后,Alice 会通过继承获得 dev 项目内资源的操作权限。Incus 实际检查的是 can_viewcan_editcan_exec 等 entitlement,adminoperatoruserviewer 是 entitlement 的权限包。

关系元组使用 OpenFGA 的 user / relation / object 三元组:

userrelationobject含义
user:aliceoperatorproject:devAlice 是 dev 项目的操作员
group:ops#memberoperatorproject:devops 组成员是 dev 项目的操作员
user:alicecan_execinstance:dev/web01Alice 只能获得 web01 的命令执行能力

关系元组的增删和查询参考 libfga

对象格式

所有对象均使用 <类型>:<标识符> 格式。项目级对象的标识符以项目名开头,不是单独的 project/instance_name 参数。

对象格式示例
Serverserver:incus
Projectproject:dev
Certificatecertificate:<完整指纹>
Storage Poolstorage_pool:local
Network Integrationnetwork_integration:ovn
Instanceinstance:dev/web01
Imageimage:dev/<完整指纹>
Image Aliasimage_alias:dev/debian
Networknetwork:dev/br0
Network ACLnetwork_acl:dev/web
Network Address Setnetwork_address_set:dev/internal
Network Zonenetwork_zone:dev/example.net
Profileprofile:dev/default
Storage Bucketstorage_bucket:dev/local/archive[/location]
Storage Volumestorage_volume:dev/local/custom/data[/location]

serverprojectshared_with 是 Incus 维护资源归属关系时使用的结构关系,不应作为普通用户权限手动修改。

模型规则

  1. 权限只做并集,没有 deny。用户通过任意一条关系路径获得 entitlement 后,不能在子对象上用另一条元组拒绝。
  2. 父级角色向下生效。Server 角色影响所有 Project,Project 角色影响该项目的资源和 Instance。
  3. 创建资源不会让创建者自动成为 owner。模型中没有 owner 关系,单独的 can_create_* 不保证创建后还能查看或管理资源。
  4. can_edit 通常包含修改、重命名和删除,不是无破坏性的“编辑配置”。
  5. 单独授予 can_execcan_update_state 等专项 entitlement 不会自动获得 can_view。CLI 可能会先查询对象,因此最小权限通常还要搭配 viewer
  6. 一个 CLI 命令可能访问多个对象。例如创建实例通常还需要查看源镜像以及所用 Profile、Network;复制和移动还会分别检查源、目标对象。
  7. 模型中包含 [user, group#member] 的 relation 可以直接授予用户或组;只有 operatorviewer from project 等计算表达式的 relation 只能通过角色或继承获得。

模型表达式示例:

define can_edit: [user, group#member] or operator from project

表示可以把 can_edit 直接授予用户或组,也可以由资源所属 Project 的 operator 自动获得。

默认权限

Incus 初始化模型时会加入:

server:incus#authenticated@user:*

所以每个已经通过认证的用户即使没有任何业务角色,仍然拥有:

因此“没有分配角色”不等于完全没有可见信息。

角色继承

三个作用域中的角色均按以下顺序包含右侧角色:

admin -> operator -> user -> viewer

Server 的同名角色会传递给所有 Project,Project 的同名角色会传递给其所有 Instance。

作用域角色实际能力
Serverviewer查看所有项目及其资源、证书、网络集成和完整 Server config
Serveruserviewer + 所有项目的 user,可进入所有实例并访问其数据面
Serveroperatoruser + 所有项目的 operator,可创建、修改、删除所有项目资源
Serveradmin完整服务器和集群管理、全局资源创建,并成为所有项目的 admin
Projectviewer查看该项目及其所有资源
Projectuserviewer + 查看项目 events/operations + 项目内所有实例的 user
Projectoperatoruser + 创建、修改、删除项目资源 + 项目内所有实例的 operator
Projectadminoperator + 修改、重命名、删除项目本身及其限制配置
Instanceviewer查看一个实例的配置、状态、日志、快照和备份信息
Instanceuserviewer + console、exec、文件、SFTP、NBD 和 TCP 转发
Instanceoperatoruser + 编辑、删除、启停、重建以及管理快照和备份
Instanceadmin当前模型中实际能力与 operator 相同,没有额外 entitlement

需要特别注意:

Server entitlement

Entitlement允许的操作
can_view查看基本服务器信息、集群状态、成员和集群组
can_view_sensitive查看完整 Server config
can_view_resources查看宿主机资源、Storage Pool resources 和非托管网卡
can_view_metrics访问 metrics;返回的实例指标继续按 Instance can_view 过滤
can_view_privileged_events查看 logging 类型的特权事件
can_edit修改服务器配置,管理集群、成员、集群组、warnings 和内部管理接口
can_create_certificates添加信任证书
can_create_projects创建 Project
can_create_storage_pools创建 Storage Pool
can_create_network_integrations创建 Network Integration
can_override_cluster_target_restrictionProject 禁止指定 Cluster target 时仍允许指定成员

Project entitlement

Entitlement允许的操作
can_view查看 Project 和 Project state
can_edit修改限制和配置、重命名、删除 Project,以及查看 Project access
can_create_instances创建实例、复制到该项目、从备份导入实例
can_create_images导入镜像或从实例发布镜像
can_create_image_aliases创建 Image Alias
can_create_profiles创建 Profile
can_create_networks创建 Network
can_create_network_acls创建 Network ACL
can_create_network_address_sets创建 Network Address Set
can_create_network_zones创建 Network Zone
can_create_storage_volumes创建、复制或导入 Storage Volume
can_create_storage_buckets创建 Storage Bucket
can_view_events查看该项目的 operation、lifecycle 和 network-acl events;不包含 logging
can_view_operations列出该项目的异步 operations

Instance entitlement

Entitlement允许的操作
can_viewlist/show/info/state,读取日志、metadata、NVRAM、快照和备份信息
can_edit修改配置、rename/move/migrate/delete、rebuild、恢复快照、修改 metadata/NVRAM
can_update_statestart、stop、restart、freeze、unfreeze
can_access_console连接 Instance console;读取 console log 只需要 can_view
can_exec在实例中执行命令,并访问 exec output
can_access_filespull、push、删除实例文件
can_connect_tcp使用 incus port-forward 连接实例端口
can_connect_nbd通过 NBD 访问实例磁盘
can_connect_sftp通过 SFTP 访问实例文件系统
can_manage_snapshots创建、修改、重命名和删除快照;恢复快照仍需要 can_edit
can_manage_backups创建、重命名、删除和导出实例备份

只希望用户在单个实例内执行命令时,建议授予该 Instance 的 viewercan_exec,不要使用会额外开放 console、文件、NBD、SFTP、TCP 的 user

其他资源 entitlement

对象can_viewcan_edit 或专项权限
Certificate查看证书信息;只能由 Server viewer 继承修改、替换、删除证书
Image查看和下载/导出镜像;Public Image 不受 OpenFGA 限制修改、删除、refresh、生成 secret
Image Alias查看 Alias修改、重命名、删除
Profile查看配置和设备修改、重命名、删除
Network查看状态、leases、forward、load balancer 和 peer;主 Network config 会被隐藏修改、重命名、删除 Network,并管理其 forward、load balancer 和 peer
Network ACL查看 ACL 规则修改、重命名、删除
Network Address Set查看地址修改、重命名、删除
Network Zone查看 Zone 和 records修改 Zone,并管理 records
Network Integration查看信息;只能由 Server viewer 继承,config 会被隐藏修改、重命名、删除
Storage Pool所有已认证用户均可查看,config/source 会被隐藏修改和删除;不能限定只查看某个 Pool
Storage Volume查看状态、bitmap、快照和备份,并可导出 Volume backup修改、移动、重命名、删除、重建、恢复快照和修改 bitmap
Storage Bucket查看 Bucket、备份和 key;读取 key 时会返回 access key 和 secret key修改 Bucket,并创建、修改、删除 key

Storage Volume 还定义了以下专项 entitlement:

Entitlement允许的操作
can_access_files读取、写入和删除卷内文件
can_connect_nbdNBD 块设备访问
can_connect_sftpSFTP 文件访问
can_manage_snapshots管理 Volume snapshots
can_manage_backups管理 Volume backups

Storage Volume 的 can_edit 会自动包含以上所有专项 entitlement。直接授予某个专项 entitlement 时不会自动得到 can_view

子资源权限归属

以下 API 资源没有独立 OpenFGA 对象,复用父对象权限:

子资源权限所属对象
Instance snapshot、backup、log、metadataInstance
Volume snapshot、backup、bitmapStorage Volume
Bucket key、backupStorage Bucket
Network forward、load balancer、peerNetwork
Network Zone recordNetwork Zone
Cluster member、cluster group、warningServer
Events、OperationsProject

Network 是共享资源的特例。Incus 可以使用 shared_with 把 Default Project 的 Network 共享给其他 Project;共享项目的 viewer 只能查看该 Network,不能修改它。

列表和数据读取语义

最小权限选择

需求建议关系
只读一个 Project 的全部资源Project viewer
使用一个 Project 的全部实例,但不能启停或改配置Project user
管理一个 Project 中的资源,但不能修改 Project 限制Project operator
只读一个 InstanceInstance viewer
只在一个 Instance 执行命令Instance viewer + can_exec
只启停一个 InstanceInstance viewer + can_update_state
完整管理一个 InstanceInstance operator
只查看或编辑一个普通资源对支持直接授权的 Image、Network、Profile、Volume 等对象授予 can_viewcan_edit 或专项 entitlement

模型没有 deny。如果需要“查看项目中除某实例外的全部资源”,不能先授予 Project viewer 再拒绝该实例,必须逐个授予允许访问的对象。

安全边界

Incus 官方明确要求:不信任其拥有宿主机 root 权限的用户不得授予以下关系:

server: admin
server: operator
server: can_edit
server: can_create_storage_pools
server: can_create_projects
server: can_create_certificates
certificate: can_edit
storage_pool: can_edit
project: admin

其余关系也必须配合严格的 Project restrictions。尤其是 Project operator,如果项目允许特权实例、宿主机磁盘或设备直通,仍可能影响宿主机。

当前 Main 已知问题

截至 2026-09-14 的 Incus main(提交 30a4243),Storage Bucket backup API 检查 storage_bucket#can_manage_backups,但 OpenFGA 模型没有为 storage_bucket 定义该 relation。因此当前代码不能正常通过这项授权,不应假设 Bucket backup 管理权限已经可用。升级 Incus 后应重新核对该问题。

模型与 API 映射来源:

实例访问

  1. 通过 WebUI 的 terminal / console 操作实例
  2. 文件上传/下载:
    1. 通过 proxy 设备配置 SSH 端口
    2. 通过 terminal 添加公钥
    3. 启动 SSH 服务:
      • Debian 系:service ssh start
      • Alpine 系:/usr/sbin/sshd
    4. 使用 ssh/scp 上传/下载文件

嵌套 OCI 容器

默认不允许在 LXC 中嵌套运行 OCI 容器。容器部署服务可直接以 OCI 实例运行在 Incus 上,并使用 Incus 网络内部通信。例外:CI/CD 中使用 Kaniko 构建 OCI 镜像。

数据设施操作

存储接口命名

按照 <接口类型>_<介质><容量><性能> 格式命名。

例如 fs_nml:文件系统接口 / NVMe / 1–4T / 性能 l。

选择存储策略

  1. 热数据:强制多副本
  2. 温/冷数据:
    • TrueNAS:RAID-Z,优先 Z2
    • Ceph:EC,温数据 4+2,冷数据 8+3 或更高
  3. 磁盘极少(每节点 1–2 盘)时使用多副本,避免 EC 小文件放大

部署 Btrfs 本地存储

Btrfs 接口为 fs,由节点本地提供。

部署 TrueNAS 共享存储

  1. TrueNAS 接口为 bs,由 TrueNAS 远程提供
  2. TrueNAS 节点命名为 nas
  3. 适用规模:3–6 节点

部署 Ceph 共享存储

  1. 适用规模:≥7 节点
  2. 命名:与计算设施同名(超融合)或 ceph-Number(独立集群)
  3. Ceph 集群网络使用独立 IP 子网,接入网口配置同网段静态 IP 且不设网关
  4. 存储接口选择:
    • fs:多节点读写,适合对 I/O 延迟不敏感的文件读写
    • bs:读写延迟双低,适合数据库
    • os:大数据或海量小文件

认证设施操作

Zitadel添加应用

Zitadel添加action

由于 Incus侧需要一个用户名,而不是sub这种长数字序列,我们在Zitadel添加以下action

function addUsername(ctx, api) {
  api.v1.claims.setClaim("preferred_username", ctx.v1.getUser().preferredLoginName);
}

触发器设置为: 自定义令牌 - access 令牌创建前

注意:admin团队已完成此步骤

创建Openfga

向admin团队申请,得到一个实例URL+api_token

基于libfga(https://codeberg.org/eoelab/libfga)操作自行设置一个store,得到store id

Incus 配置 OIDC

Incus 配置Openfga

网络设施操作

物理网络架设

根据带宽选择方案:

带宽方案
1/2.5G电口(RJ45 + CAT6),无 RDMA
10G光口(SFP+ + DAC)+ RoCEv2
≥40G光口(QSFP+ + DAC)+ 强制 RoCEv2

注意:使用 RoCEv2 需要支持 PFC 和 ECN 的网卡与交换机;光口默认使用 DAC 线,无需光模块。

公网接入

  1. 使用硬件路由器/防火墙作为本地域网关
  2. 一个本地域只绑定一个子域名证书作为公网出口
  3. NAT 型:本地域入口解析到网关,通过端口转发/DMZ 主机转发到节点
  4. 互通型:本地域入口直接解析到节点

虚拟网络配置

  1. 单节点使用 bridge,集群使用 ovn,整个本地域有且仅有一个虚拟网络
  2. 用户态接口命名:INTERFACE-Domain
  3. 地址池默认使用 172.16.0.0/12
  4. 实例默认接入设备 eth0;VM 需要 proxy 设备时可设置静态地址:
    eth0:
        ipv4.address: 实例静态ip
        network: 接入网络
        type: nic
    
  5. 实例使用 proxy 设备暴露服务:
    • 容器(lxc/oci):Listen 为外部端口,connect 为内部端口
    • vm:NAT mode 启用,Listen 的 IP 为节点 IP,connect 的 IP 为实例静态 IP

ACL 配置示例

  1. block-host:丢弃主机地址段流量:

    • Drop Any 10.0.0.0/8
    • Drop Any 192.168.0.0/16
  2. block-internal:丢弃内部地址段流量:

    • Drop Any 172.16.0.0/12

加入联邦

如何获得用户账户

  1. 访问 https://authn.eoelab.org 自主注册,或基于 GitHub 创建账户
    • 此时不会得到任何权限
    • 基于外部 IDP 创建账户后,由于空密码将无法自主重置密码,必须联系 admin 团队设置初始密码
  2. 向 admin 团队邮件/协作设施发送自我介绍,说明身份、技术背景或使用目的
  3. admin 团队审核通过后,Zitadel 账户将被赋予基本用户权限(core 项目角色权限)

申请人需满足以下任一条件:

获得用户权限后,才可以将设备加入联邦。

退出与清理

EOELAB 不支持静默退出。需要退出时向 admin 团队发送退出邮件,admin 团队将执行:

对于本地域,还包括:

长期失联或存在安全风险的节点可能被强制移除。

客户端加入联邦网络

  1. 下载客户端:https://tailscale.com/download
  2. 执行:
    sudo tailscale up --login-server https://hs.eoelab.org
    
  3. 更多细节参考:https://headscale.net/stable/usage/getting-started/

注意:在云服务器上激活客户端可能导致内部镜像解析到 CGNAT 范围,可换源到公网站点(如 USTC 镜像源)。

部署 DERP 中继节点

  1. 下载客户端并登录:
    tailscale login --login-server https://hs.eoelab.org
    
  2. 使用以下 Docker Compose 部署 DERP(放行 3478/12345 端口):
    services:
      derper:
        image: ghcr.io/yangchuansheng/derper:v1.98.8
        ports:
          - 3478:3478/udp
          - 12345:12345
        environment:
          DERP_DOMAIN: example.com
          DERP_CERT_DIR: /cert
          DERP_ADDR: ':12345'
          DERP_STUN_PORT: '3478'
          DERP_HTTP_PORT: '-1'
          DERP_VERIFY_CLIENTS: "true"
        volumes:
          - ./cert:/cert
          - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
    
  3. https://codeberg.org/eoelab/Derpmap 提交 PR 增加节点,注意:
    • 区域代码为 chn(ISO 3166-1 三字母规范),区域名称使用国家全称
    • 中国大陆(chn, ID 为 900)只接收来自中国大陆的中继节点,港澳台除外
    • 建议 DERP 启用客户端验证避免滥用

注意:不接受自签名节点,必须包含公共 CA 证书;中国大陆云服务器必须使用备案域名作为入口点。

原生设施使用

申请联邦域名与证书

具备公网的本地域/服务设备默认可获得 eoelab.org 子域名。节点本地生成并保存私钥,联邦设施基于 DNS-01 challenge 完成 ACME 验证与证书签发。节点通过唯一身份凭证获取自身被授权域名的证书。

申请自托管 Runner

  1. 在 Codeberg Actions 页面创建新的 runner
  2. 将以下内容发送给 admin 团队:
    connections:
      forgejo:
        url: https://codeberg.org/
        uuid: UUID
        token: TOKEN
    
    • 实际注册时 forgejo 将替换为申请人的用户名,用于内部区分、避免同名 key 冲突

通用 runner tag

维度取值
sizetiny(2–4G)、small(4–8G)、medium(8–16G)
archamd64、riscv64
runtimelxc(标准)、vm(全功能)

专用 runner tag

使用监控设施

用途endpoint框架
数据源VictoriaMetrics
可视化Grafana
日志VictoriaLogs
告警Alertmanager

部署检查清单

本地域节点

数据设施

网络设施

加入联邦

Post list